package com.dpiinc.TechPage.repository

import android.util.Log
import com.dpiinc.TechPage.AWLog
import com.dpiinc.TechPage.api.EditNoteApi
import com.dpiinc.TechPage.api.asyncSubscribe
import com.dpiinc.TechPage.oss.OssFileManager
import com.dpiinc.TechPage.oss.UploadTask
import com.dpiinc.TechPage.room.RoomAiWriterDatabase
import com.dpiinc.TechPage.room.bean.NoteEntity
import com.dpiinc.TechPage.utils.DateUtils
import com.beiji.lib.pen.cache.PenCacheManager

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData


/**
 * 新建笔记、编辑笔记 Repository
 * Created by X on 2018/7/7.
 */
class EditNoteRepository(val db: RoomAiWriterDatabase, private val editNoteApi: EditNoteApi) {

    companion object {
        const val OPERATION_SAVE = 0
        const val OPERATION_DELETE = 2
        const val OPERATION_CLEAR = 3

    }

    private fun isLocalNote(note: NoteEntity): Boolean {
        return note.noteId.startsWith("_")
    }

    fun saveToLocal(note: NoteEntity) {
        if (db.noteDao().getNote(note.noteId).isNotEmpty()) {
            db.noteDao().update(note)
        } else {
            db.noteDao().insert(note)
        }
    }

    fun save(note: NoteEntity): LiveData<NetworkState> {
        saveToLocal(note)
        //还未同步
        return if (isLocalNote(note)) {
            Log.i("TAG", "save:isLocalNote(note)")
            addNewNote(note)
        } else {
            Log.i("TAG", "save:!isLocalNote(note)")
            editNote(note)
        }
    }

    fun saveLocalNote(note: NoteEntity) {
        if (isLocalNote(note)) {
            //TODO Yang
            // addNewNote(note,true)
            addNewNote(note)
        }
    }

    fun delete(note: NoteEntity): LiveData<NetworkState> {
        val operationState = MutableLiveData<NetworkState>()
        if (isLocalNote(note)) {
            db.noteDao().delete(note)
            PenCacheManager.instance.removeCache(note.noteId, true)
            operationState.value = NetworkState(OPERATION_DELETE, Status.SUCCESS)
            return operationState
        }
        editNoteApi.delete(note)
                .asyncSubscribe({
                    if (it.isSuccess) {
                        db.noteDao().delete(note)
                        PenCacheManager.instance.removeCache(note.noteId, true)
                        operationState.value = NetworkState(OPERATION_DELETE, Status.SUCCESS)
                    } else {
                        operationState.value = NetworkState(OPERATION_DELETE, Status.FAILED, "errorCode:${it.errorCode}")
                    }
                }, {
                    operationState.value = NetworkState(OPERATION_DELETE, Status.FAILED, it.message)
                })
        return operationState
    }

    fun getLastNote(): NoteEntity? {
        val noteList = db.noteDao().getLastNote()
        if (noteList.isNotEmpty()) {
            return noteList[0]
        }
        return null
    }

    //TODO Yang
//private fun addNewNote(note: NoteEntity,isDelete:Boolean = false): LiveData<NetworkState> {
    private fun addNewNote(note: NoteEntity): LiveData<NetworkState> {
        Log.i("TAG", "addNewNote: ------------")

        val operationState = MutableLiveData<NetworkState>()
        editNoteApi.add(note)
                .asyncSubscribe({
                    if (it.isSuccess) {
                        Log.i("TAG", "addNewNote: ${it.isSuccess}")
                        it.result?.let {
                            val localNoteId = note.noteId
                            db.noteDao().delete(note)
                            note.noteId = it.noteId
                            db.noteDao().insert(note)
                            PenCacheManager.instance.moveCache(localNoteId, note.noteId) { result ->
                                if (result) {
                                    PenCacheManager.instance.loadAsCurrentCache(note.noteId) {
                                        Log.i("TAG", "addNewNote: PenCacheManager.instance.loadAsCurrentCache(note.noteId)")
                                        refreshUploadTask(localNoteId, note.noteId)
                                        //TODO Yang
                                        //uploadFiles(note, operationState,isDelete)
                                        uploadFiles(note, operationState)
                                    }
                                } else {
                                    Log.i("TAG", "addNewNote: !PenCacheManager.instance.loadAsCurrentCache(note.noteId)")
                                    operationState.value = NetworkState(OPERATION_SAVE, Status.FAILED, "move cache failed")
                                }
                            }
                            return@asyncSubscribe
                        }
                        //TODO Yang
                        //isLocalNote(note)
                    }
                    Log.i("TAG", "addNewNote:failed ")
                    operationState.value = NetworkState(OPERATION_SAVE, Status.FAILED, "errorCode:${it.errorCode}")
                }, {
                    Log.i("TAG", "addNewNote:failed//${it.message} ")
                    operationState.value = NetworkState(OPERATION_SAVE, Status.FAILED, it.message)
                })
        return operationState
    }

    private fun refreshUploadTask(srcKey: String, desKey: String) {
        val oldTaskList = db.uploadTaskDao().getTasksById(srcKey)
        oldTaskList.forEach {
            val newTask = UploadTask(desKey, it.fileType, it.index).apply {
                noteId = desKey
                userId = it.userId
                fileName = PenCacheManager.instance.modifyCacheFileName(it.fileName, srcKey, desKey)
                filePath = PenCacheManager.instance.getCacheFilePath(fileName, desKey)
                time = it.time
            }
            Log.i("TAG", "refreshUploadTask:${newTask.toString()}")
            db.uploadTaskDao().insert(newTask)
            db.uploadTaskDao().delete(it)
        }
    }

    private fun editNote(note: NoteEntity): LiveData<NetworkState> {
        val operationState = MutableLiveData<NetworkState>()
        editNoteApi.edit(note)
                .asyncSubscribe({
                    if (it.isSuccess) {
                        uploadFiles(note, operationState)
                    } else {
                        operationState.value = NetworkState(OPERATION_SAVE, Status.FAILED, "errorCode:${it.errorCode}")
                    }
                }, {
                    operationState.value = NetworkState(OPERATION_SAVE, Status.FAILED, it.message)
                })
        return operationState
    }

    private fun clearNote(note: NoteEntity): LiveData<NetworkState> {
        val operationState = MutableLiveData<NetworkState>()
        editNoteApi.clear(note)
                .asyncSubscribe({
                    if (it.isSuccess) {

                    } else {
                        operationState.value = NetworkState(OPERATION_CLEAR, Status.RUNNING)
                    }
                }, {
                    operationState.value = NetworkState(OPERATION_CLEAR, Status.RUNNING)
                })
        return operationState
    }

    fun doOperation(operation: Int, note: NoteEntity): LiveData<NetworkState> {
        val operationState = MutableLiveData<NetworkState>()
        return when (operation) {
            OPERATION_SAVE -> save(note)
            OPERATION_DELETE -> delete(note)
            OPERATION_CLEAR -> clearNote(note)
            else -> operationState
        }
    }

    //TODO Yang
//private fun uploadFiles(note: NoteEntity, operationState: MutableLiveData<NetworkState>) {
    private fun uploadFiles(note: NoteEntity, operationState: MutableLiveData<NetworkState>) {
        val updateTime = DateUtils.getCurrentTimeMillis()
        val curCacheModel = PenCacheManager.instance.getCurrentCache()
        if (curCacheModel == null) {
            operationState.postValue(NetworkState(OPERATION_SAVE, Status.SUCCESS))
            return
        }
        val uploadTasks = db.uploadTaskDao().getTasksById(note.noteId)
        if (uploadTasks.isEmpty()) {
            operationState.postValue(NetworkState(OPERATION_SAVE, Status.SUCCESS))
            return
        }
        uploadTasks.forEach {
            it.time = updateTime
        }
        var processFlag = 0f
        OssFileManager.instance.asyncPutFiles(uploadTasks) { task, resultData, progress, isComplete ->
            AWLog.e("upload", "$progress.........$resultData")
            if (progress > processFlag) {
                db.uploadTaskDao().delete(task)
                processFlag = progress
            }
            if (isComplete) {
                if (progress == 1f) {
                    operationState.postValue(NetworkState(OPERATION_SAVE, Status.SUCCESS))
                    //TODO Yang
                    //if (isDelete)
                    //        PenCacheManager.instance.removeTempCache(note.noteId)
                } else {
                    operationState.postValue(NetworkState(OPERATION_SAVE, Status.FAILED, "upload failed"))
                }
            }
        }
    }

    fun insertUploadTask(uploadTask: UploadTask) {
        db.uploadTaskDao().insert(uploadTask)
    }

}